/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.model.elements;

import org.jfonia.connect5.basics.BasicValueNode;
import org.jfonia.connect5.basics.MutableValueNode;
import org.jfonia.connect5.basics.Observer;
import org.jfonia.constants.ViewConstants;

/**
 *
 * @author Rik Bauwens
 */
public class Clef extends MusicalElement implements IStaffElement
{
        //Glyph types
        public enum Type
        {
                G, F, C, Gminus8, Gplus8, Fminus8, Fplus8;
                
                public static Type toType(String string)
                {
                        return Type.valueOf(string);
                }

                public static String toString(Type type)
                {
                        return type.name();
                }

                public static Type toType(int value)
                {
                        if(value == ViewConstants.G_CLEF)
                                return G;
                        else if(value == ViewConstants.F_CLEF)
                                return F;
                        else if(value == ViewConstants.C_CLEF)
                                return C;
                        else if(value == ViewConstants.G_MINUS8_CLEF)
                                return Gminus8;
                        else if(value == ViewConstants.G_PLUS8_CLEF)
                                return Gplus8;
                        else if(value == ViewConstants.F_MINUS8_CLEF)
                                return Fminus8;
                        else if(value == ViewConstants.F_PLUS8_CLEF)
                                return Fplus8;
                        return null;
                }

                public static int toInt(Type type)
                {
                        if(type == G)
                                return ViewConstants.G_CLEF;
                        else if(type == F)
                                return ViewConstants.F_CLEF;
                        else if(type == C)
                                return ViewConstants.C_CLEF;
                        else if(type == Gminus8)
                                return ViewConstants.G_MINUS8_CLEF;
                        else if(type == Gplus8)
                                return ViewConstants.G_PLUS8_CLEF;
                        else if(type == Fminus8)
                                return ViewConstants.F_MINUS8_CLEF;
                        else if(type == Fplus8)
                                return ViewConstants.F_PLUS8_CLEF;
                        return -1;
                }
        };

        public final static Clef trebleClef = new Clef().setType(Type.G).setStaffRank(2).setCentralCRank(-2);
        public final static Clef bassClef   = new Clef().setType(Type.F).setStaffRank(6).setCentralCRank(10);
        public final static Clef altoClef   = new Clef().setType(Type.C).setStaffRank(4).setCentralCRank(4);
        public final static Clef tenorClef  = new Clef().setType(Type.C).setStaffRank(6).setCentralCRank(6);

        private MutableValueNode<Type> typeNode;
        private MutableValueNode<Integer> staffRankNode;
        private MutableValueNode<Integer> centralCRankNode;

        public Clef()
        {
                this(0);
        }

        /**
         * Construct new Clef
         * @param type G, F or C
         * @param staffRank y-position on staff, counting op from the bottom staff line, per 'tone'
         * @param centralCRank staffRank of central C
         */
        public Clef(int difference)
        {
                super(difference);
                //Default: treble clef
                this.typeNode = new BasicValueNode<Type>(Type.G);
                this.staffRankNode = new BasicValueNode<Integer>(2);
                this.centralCRankNode = new BasicValueNode<Integer>(-2);
                typeNode.addObserver(new Observer()
                {
                        public void onNotify(Object source)
                        {
                                if(getType() == Type.G)
                                        setStaffRank(2).setCentralCRank(-2);
                                else if(getType() == Type.F)
                                        setStaffRank(6).setCentralCRank(3);
                                else if(getType() == Type.C)
                                        setStaffRank(4).setCentralCRank(4);
                                else if(getType() == Type.Gminus8)
                                        setStaffRank(2).setCentralCRank(-9);
                                else if(getType() == Type.Gplus8)
                                        setStaffRank(2).setCentralCRank(5);
                                else if(getType() == Type.Fminus8)
                                        setStaffRank(6).setCentralCRank(-4);
                                else if(getType() == Type.Fplus8)
                                        setStaffRank(6).setCentralCRank(10);
                        }
                });
        }

        //Integer denoting the type of glyphs (treble, bass, ut)
        public Type getType()
        {
                return typeNode.getValue();
        }

        //Y-staff-coordinate for glyph (e.g. standard treble is at 6, standard bass at 2)
        public int getStaffRank()
        {
                return staffRankNode.getValue();
        }

        public int getCentralCRank()
        {
                return centralCRankNode.getValue();
        }

        public Clef setType(Type type)
        {
                typeNode.setValue(type);
                return this;
        }

        public Clef setStaffRank(int staffRank)
        {
                staffRankNode.setValue(staffRank);
                return this;
        }

        public Clef setCentralCRank(int centralCRank)
        {
                centralCRankNode.setValue(centralCRank);
                return this;
        }

        public MutableValueNode<Type> getTypeNode()
        {
                return typeNode;
        }

        public MutableValueNode<Integer> getCentralCRankNode()
        {
                return centralCRankNode;
        }

        public MutableValueNode<Integer> getStaffRankNode()
        {
                return staffRankNode;
        }

        @Override
        public Clef clone(){
            Clef clef = new Clef(getDifference()).setType(getType())
                                                 .setStaffRank(getStaffRank())
                                                 .setCentralCRank(getCentralCRank());
            return clef;
        }
}
